package ink.xiaobaibai.serviceOxy.pay.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import ink.xiaobaibai.bo.UserAndDep;
import ink.xiaobaibai.common.*;
import ink.xiaobaibai.entity.*;
import ink.xiaobaibai.enumOxy.*;
import ink.xiaobaibai.service.*;
import ink.xiaobaibai.serviceOxy.IRedisUtils;
import ink.xiaobaibai.serviceOxy.ISmsService;
import ink.xiaobaibai.serviceOxy.onePay.IDeviceOzoneControlService;
import ink.xiaobaibai.serviceOxy.pay.IPayHttpService;
import ink.xiaobaibai.serviceOxy.pay.IPayService;
import ink.xiaobaibai.util.WxPayKeyInfo;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @description: 支付实现类
 * @author: 小白白
 * @create: 2021-05-21
 **/

@Service
@Slf4j
public class PayServiceImpl implements IPayService {

    private static ThreadLocal<String> orderThreadLocal = new ThreadLocal<>();

    /**
     * 本原因无需回调,因为押了,但未去开通月份,就不用回调了
     */
    public static String reasonNoNotifyUrl = "原押金退款";

    // redis押金标识
    public static final String ORDER_DEP = "order_dep:";

    @Autowired
    private IPayHttpService payHttpService;

    @Autowired
    private IClientUserService clientUserService;

    @Autowired
    private IClientOrderService clientOrderService;

    @Autowired
    private IMonthlyfeeOrderService monthlyfeeOrderService;

    @Autowired
    private IMonthlyfeeDepositService monthlyfeeDepositService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private IOzoneDeviceService ozoneDeviceService;

    @Autowired
    private IDeviceOzoneControlService deviceControlService;

    @Autowired
    private IAdminUserService adminUserService;

    @Autowired
    private IMonthlyRefundDepositService refundDepositService;

    @Autowired
    private IMonthlyfeeDepositService depositService;

    @Autowired
    private IMonthlyUserDeviceService userDeviceService;

    @Autowired
    private IMonthlyfeeDeviceService monthlyfeeDeviceService;

    @Autowired
    private IBuyOrderService buyOrderService;

    @Autowired
    private IBuyOzoneDeviceService buyOzoneDeviceService;

    @Autowired
    private IBuyOxygenDeviceService buyOxygenDeviceService;

    @Autowired
    private ILogisticsService logisticsService;

    @Autowired
    private ILogisticsBuyService logisticsBuyService;

    @Autowired
    private IRedisUtils redisUtils;

    @Autowired
    private ICouponService couponService;

    @Autowired
    private ICouponUserService couponUserService;

    @Autowired
    private ICouponCodeService couponCodeService;

    @Autowired
    private ICouponCodeLogService couponCodeLogService;

    @Autowired
    private ISmsService smsService;

    @Autowired
    private IProductDeviceService productDeviceService;

    private BigDecimal validAmount(BigDecimal amount) {
        if (amount.doubleValue() < 0.01) {
            amount = new BigDecimal("0.01");
        }
        return amount;
    }

    @Override
    public WxPayment onePay(BigDecimal amount, Integer userId, Integer deviceId) {
        amount = this.validAmount(amount);
        //支付基本参数
        PayBaseInfo payBaseInfo = this.getBaseInfo(amount, userId, PayType.SinglePay);
        //支付请求体
        WxPayPrefixOrder wxPayPrefixOrder = new WxPayPrefixOrder(payBaseInfo, deviceId.toString());
        //预下单id
        String prepareOrderId = this.getPrepareOrderId(wxPayPrefixOrder);
        orderThreadLocal.set(payBaseInfo.getOrderId());
        return new WxPayment(prepareOrderId);
    }

    @Override
    public WxPayment depositPay(BigDecimal amount, Integer userId) {
        amount = this.validAmount(amount);
        /**
         * 押金支付,注意可以连续交付押金,即又包月了一台
         */
        //支付基本参数
        PayBaseInfo payBaseInfo = this.getBaseInfo(amount, userId, PayType.DepositPay);
        //支付请求体
        WxPayPrefixOrder wxPayPrefixOrder = new WxPayPrefixOrder(payBaseInfo, userId.toString());
        //预下单id
        String prepareOrderId = this.getPrepareOrderId(wxPayPrefixOrder);
        return new WxPayment(prepareOrderId);
    }

    @Override
    public WxPayment monthlyNewPay(BigDecimal amount, Integer userId, Integer adminUserId) {
        amount = this.validAmount(amount);
        //支付基本参数
        PayBaseInfo payBaseInfo = this.getBaseInfo(amount, userId, PayType.MonthlyPay_NEW);
        //支付请求体
        WxPayPrefixOrder wxPayPrefixOrder =
                new WxPayPrefixOrder(payBaseInfo, adminUserId.toString());
        //预下单id
        String prepareOrderId = this.getPrepareOrderId(wxPayPrefixOrder);
        orderThreadLocal.set(payBaseInfo.getOrderId());
        return new WxPayment(prepareOrderId);
    }

    @Override
    public WxPayment monthlyContinuePay(BigDecimal amount, Integer userId, Integer deviceId) {
        amount = this.validAmount(amount);
        //支付基本参数
        PayBaseInfo payBaseInfo = this.getBaseInfo(amount, userId, PayType.MonthlyPay_CONTINUE);
        //支付请求体
        WxPayPrefixOrder wxPayPrefixOrder =
                new WxPayPrefixOrder(payBaseInfo, deviceId.toString());
        //预下单id
        String prepareOrderId = this.getPrepareOrderId(wxPayPrefixOrder);
        orderThreadLocal.set(payBaseInfo.getOrderId());
        return new WxPayment(prepareOrderId);
    }

    @Override
    public WxPayment buyPay(BigDecimal amount, Integer userId, Integer adminUserId) {
        amount = this.validAmount(amount);
        PayBaseInfo payBaseInfo = this.getBaseInfo(amount, userId, PayType.BUY_PAY);
        WxPayPrefixOrder wxPayPrefixOrder =
                new WxPayPrefixOrder(payBaseInfo, adminUserId.toString());
        String prepareOrderId = this.getPrepareOrderId(wxPayPrefixOrder);
        return new WxPayment(prepareOrderId);
    }

    @Override
    public boolean buyRefund(String orderId) {
        BuyOrder buyOrder = this.buyOrderService.getById(orderId);
        this.payHttpService.returnAmount(orderId, buyOrder.getAmount(), PayType.BUY_REFUND.getOrderPrefix() + orderId, buyOrder.getAmount(), "购买业务退款");
        return true;
    }

    @Override
    public CallbackResult decryptPayResponseObj(String responseBody) {
        JSONObject jsonObject = JSONObject.parseObject(responseBody);
        JSONObject resourceObj = jsonObject.getJSONObject("resource");
        if (resourceObj == null) {
            return null;
        }
        String associatedData = resourceObj.getString("associated_data");
        String nonce = resourceObj.getString("nonce");
        String ciphertext = resourceObj.getString("ciphertext");
        if (associatedData == null || nonce == null || ciphertext == null) {
            return null;
        }
        String result;
        try {
            result = WxPayKeyInfo.decryptResponseBody(
                    WxCommon.APIV3KEY,
                    associatedData,
                    nonce,
                    ciphertext
            );
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return new CallbackResult(result);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean handleCallback(CallbackResult callbackResult) {
        log.info("回调内容:{}", callbackResult);
        if (!StringUtils.equals(callbackResult.tradeState, "SUCCESS")) {
            String refundStatus = callbackResult.getRefundStatus();
            if (refundStatus != null && StringUtils.equals(refundStatus, "SUCCESS")) {
                // 退款信息可以通过
            } else {
                //没支付成功,就不理他
                log.error(callbackResult.toString());
                return false;
            }
        }


        if (this.stringRedisTemplate.opsForValue().get(callbackResult.getTransactionId()) != null) {
            //已经被消费过了
            log.error("回调过快");
            return false;
        }
        String orderId = callbackResult.getOutTradeNo();
        if (orderId.startsWith(PayType.SinglePay.getOrderPrefix())) {
            //单次
            QueryWrapper<ClientOrder> q1 = new QueryWrapper<>();
            q1.eq("order_id", callbackResult.getTransactionId());
            if (this.clientOrderService.count(q1) == 1) {
                log.error("遇到了重复单次成功消息");
                return true;
            }
            this.handleCallback(callbackResult, PayType.SinglePay);
        } else if (callbackResult.getRefundStatus() == null && orderId.startsWith(PayType.DepositPay.getOrderPrefix())) {
            //非退款 交付押金
            QueryWrapper<MonthlyfeeDeposit> q1 = new QueryWrapper<>();
            q1.eq("order_id", orderId);
            if (this.depositService.count(q1) == 1) {
                log.error("遇到了重复的押金支付成功消息");
                return true;
            }
            this.handleCallback(callbackResult, PayType.DepositPay);
        } else if (orderId.startsWith(PayType.MonthlyPay_NEW.getOrderPrefix())) {
            //新开通
            QueryWrapper<MonthlyfeeOrder> q1 = new QueryWrapper<>();
            q1.eq("order_id", orderId);
            if (this.monthlyfeeOrderService.count(q1) == 1) {
                log.error("遇到了重复的新开通支付成功消息");
                return true;
            }
            this.handleCallback(callbackResult, PayType.MonthlyPay_NEW);
        } else if (orderId.startsWith(PayType.MonthlyPay_CONTINUE.getOrderPrefix())) {
            //续租
            QueryWrapper<MonthlyfeeOrder> q1 = new QueryWrapper<>();
            q1.eq("order_id", orderId);
            if (this.monthlyfeeOrderService.count(q1) == 1) {
                log.error("遇到了重复的续约支付成功消息");
                return true;
            }
            this.handleCallback(callbackResult, PayType.MonthlyPay_CONTINUE);
        } else if (orderId.startsWith(PayType.REFUND_PAY.getOrderPrefix())) {
            //押金退款
            orderId = orderId.substring(2);
            QueryWrapper<MonthlyRefundDeposit> q1 = new QueryWrapper<>();
            q1.eq("id", Integer.parseInt(orderId));
            q1.eq("status", ReturnDepositStatus.OK.getStatus());
            if (this.refundDepositService.count(q1) == 1) {
                log.error("遇到了重复退款成功消息");
                return true;
            }
            this.handleCallback(callbackResult, PayType.REFUND_PAY);
        } else if (orderId.startsWith(PayType.BUY_PAY.getOrderPrefix())) {
            //购买支付
            QueryWrapper<BuyOrder> q1 = new QueryWrapper<>();
            q1.eq("order_id", orderId);
            if (this.buyOrderService.count(q1) == 1) {
                log.error("遇到了重复购买支付成功消息");
                return true;
            }
            this.handleCallback(callbackResult, PayType.BUY_PAY);
        } else if (orderId.startsWith(PayType.BUY_REFUND.getOrderPrefix())) {
            //购买款退款
            QueryWrapper<BuyOrder> q1 = new QueryWrapper<>();
            q1.select("status");
            q1.eq("id", orderId);
            BuyOrder buyOrder = this.buyOrderService.getOne(q1);
            if (buyOrder.getStatus().equals(BuyOrderStatus.refunded.getStatus())) {
                log.error("遇到了重复退款成功消息");
                return true;
            }
            this.handleCallback(callbackResult, PayType.BUY_REFUND);
        }
        //防止微信支付太快了,两个成功请求进入
        this.stringRedisTemplate.opsForValue().set(callbackResult.getTransactionId(), "1", 3, TimeUnit.SECONDS);
        return true;
    }

    @Override
    public boolean refundByDepositIdWhitNoMon(String depositId) {
        MonthlyfeeDeposit deposit = this.depositService.getById(depositId);
        this.payHttpService.returnAmount(depositId, deposit.getAmount(), "no" + depositId, deposit.getAmount(), reasonNoNotifyUrl);
        //删除对应押金表记录即可
        this.depositService.removeById(depositId);
        return true;
    }

    @Override
    public boolean refundPayAmount(Integer refundDepositId) {
        MonthlyRefundDeposit refundDeposit = this.refundDepositService.getById(refundDepositId);
        String depositId = refundDeposit.getDepositId();
        BigDecimal amount = refundDeposit.getAmount();
        MonthlyfeeDeposit deposit = this.depositService.getById(depositId);
        this.payHttpService.returnAmount(depositId, amount, refundDepositId.toString(), deposit.getAmount(), "押金退款");
        return true;
    }

    /**
     * 通过臭氧机器id获取adminId和部门id
     *
     * @param deviceId
     * @return
     */
    private UserAndDep getAdminUserAndDepByDeviceId(Integer deviceId) {
        return this.ozoneDeviceService.getAdminUserAndDepByDeviceId(deviceId);
    }

    @Data
    @SuppressWarnings("all")
    public static class WxPayPrefixOrder {

        public WxPayPrefixOrder(PayBaseInfo payBaseInfo, String attach) {
            this.description = payBaseInfo.getDesc();
            this.attach = attach;
            this.out_trade_no = payBaseInfo.getOrderId();
            this.amount = new Amount(payBaseInfo.getPenny());
            this.payer = new Payer(payBaseInfo.getOpenid());
            this.appid = WxCommon.APPID;
            this.mchid = WxCommon.MCHID;
            Date fairDate = DateUtils.addMinutes(new Date(), 2);//2分钟内付款
            this.time_expire = DateFormatUtils.format(fairDate, "YYYY-MM-dd HH:mm:ss").replaceFirst(" ", "T") + "+08:00";
            this.notify_url = WxCommon.NOTIFY_URL;
        }

        private String appid;//appId

        private String mchid;//商户号

        private String attach;//自定义附加数据

        private String description;//商品描述

        private String out_trade_no;//本系统内部订单号

        private String time_expire;//交易结束时间 格式:2015-05-20T13:29:35+08:00(+08:00固定)

        private String notify_url;//回调通知地址

        private Amount amount;//金额对象,单位为分

        private Payer payer;//支付者,传入openid即可

    }

    @Data
    private static class Payer {

        public Payer() {

        }

        public Payer(String openid) {
            this.openid = openid;
        }

        private String openid;
    }

    @Data
    @NoArgsConstructor
    private static class Amount {

        public Amount(int total) {
            this.total = total;
        }

        private int total;//总金额单位为:分
    }

    @Data
    public class CallbackResult {

        public CallbackResult(String responseBody) {
            JSONObject jsonObject = JSONObject.parseObject(responseBody);
            this.transactionId = jsonObject.getString("transaction_id");
            this.outTradeNo = jsonObject.getString("out_trade_no");
            if (jsonObject.getString("out_refund_no") != null) {
                this.outTradeNo = jsonObject.getString("out_refund_no");
            }
            this.attach = jsonObject.getString("attach");
            this.tradeState = jsonObject.getString("trade_state");
            this.payer = JSONObject.parseObject(jsonObject.getString("payer"), Payer.class);
            double cent = Integer.parseInt(jsonObject.getJSONObject("amount").getString("payer_total"));
            this.payerTotal = new BigDecimal(String.valueOf((cent / 100D)));
            if (jsonObject.getString("out_refund_no") == null) {
                this.userId = Integer.parseInt(this.outTradeNo.substring(6));
            }
            this.refundStatus = jsonObject.getString("refund_status");
//            this.valid();
        }

        //微信支付订单号(防止重复消息)
        private String transactionId;

        //内部飘渺订单号
        private String outTradeNo;

        //附加数据
        private String attach;

        //支付者
        private Payer payer;

        //支付状态
        private String tradeState;

        //支付金额,元
        private BigDecimal payerTotal;

        //用户id
        private Integer userId;

        // 退款状态
        private String refundStatus;

//        private void valid() {
//            if(transactionId==null||outTradeNo==null||attach==null||tradeState==null||payerTotal==null){
//                log.error("严重错误,错误信息进入回调");
//                throw new RuntimeException("严重错误");
//            }
//        }

        @Override
        public String toString() {
            return "支付回调:内部订单号:" + this.outTradeNo + ",支付状态:" + this.tradeState + "支付金额:" + this.payerTotal;
        }

    }

    @Data
    private class PayBaseInfo {

        public PayBaseInfo(BigDecimal amount, Integer userId, PayType payType) {
            this.openid = PayServiceImpl.this.getOpenidByUserId(userId);
            this.orderId = payType.getOrderPrefix() + PayServiceImpl.this.getOrderIdSuffix(userId);
            this.penny = PayServiceImpl.this.yuanConvertToPenny(amount);
            this.desc = payType.getDescription();
        }

        private String openid;

        private String orderId;

        private int penny;

        private String desc;

    }

    /**
     * 钱转为分
     */
    private int yuanConvertToPenny(BigDecimal amount) {
        return (int) (amount.doubleValue() * 100);
    }

    /**
     * 获取用户openId
     */
    private String getOpenidByUserId(Integer userId) {
        QueryWrapper<ClientUser> q1 = new QueryWrapper<>();
        q1.select("user_openid");
        q1.eq("id", userId);
        return this.clientUserService.getOne(q1).getUserOpenid();
    }

    /**
     * 获取不重复的通用orderId
     */
    private String getOrderIdSuffix(Integer userId) {
        String midOrderStr = String.valueOf(System.currentTimeMillis()).substring(9);
        String endOrderStr = StringUtils.leftPad(userId.toString(), 8, "0");
        return midOrderStr + endOrderStr;
    }

    /**
     * 分-openid-orderId 三者必须
     */
    private PayBaseInfo getBaseInfo(BigDecimal amount, Integer userId, PayType payType) {
        return new PayBaseInfo(amount, userId, payType);
    }

    /**
     * 获取预下单id
     */
    private String getPrepareOrderId(WxPayPrefixOrder wxPayPrefixOrder) {
        return "prepay_id=" + this.payHttpService.prepareOrder(wxPayPrefixOrder);
    }

    /**
     * 回调结果处理方法
     */
    private void handleCallback(CallbackResult callbackResult, PayType payType) {
        String orderId = callbackResult.getOutTradeNo();
        Integer userId = callbackResult.getUserId();
        BigDecimal amountSum = callbackResult.getPayerTotal();
        switch (payType) {
            case SinglePay:
                // 优惠码或者优惠券 消耗回调
                this.couponService.consumeCoupon(orderId, userId);
                this.couponCodeService.consumeCouponCode(orderId, userId);

                String timeStr = this.redisUtils.getOnePatFunctionTime(orderId);
                if (timeStr == null) {
                    // 历史消息,启动时间已经丢失
                    log.error("历史单次支付记录,启动时间已经丢失,{}", JSON.toJSON(callbackResult));
                    return;
                }
                Integer secondsTime = Integer.parseInt(timeStr);
                Integer deviceIdSingle = Integer.parseInt(callbackResult.getAttach());
                UserAndDep obj = this.getAdminUserAndDepByDeviceId(deviceIdSingle);
                //创建订单对象
                ClientOrder clientOrder = new ClientOrder(callbackResult.getOutTradeNo(), userId, amountSum, deviceIdSingle,
                        obj.getUserId(), obj.getDepId(), secondsTime);
                this.clientOrderService.save(clientOrder);
                //发送启动请求
                this.deviceControlService.openDeviceByOnePay(deviceIdSingle, orderId);
                break;

            case DepositPay:
                //空闲押金,未对机器进行绑定
                String str = this.stringRedisTemplate.opsForValue().get(Common.DEPOSIT_PRE + userId);
                ClientInfo clientInfo = JSON.parseObject(str, ClientInfo.class);
                MonthlyfeeDeposit monthlyfeeDeposit =
                        new MonthlyfeeDeposit(orderId, userId, -1, amountSum, DepositStatus.FREE.getStatus(),
                                clientInfo.getName(), clientInfo.getPhone(), clientInfo.getAddress(), clientInfo.getAdminUserId());
                this.monthlyfeeDepositService.save(monthlyfeeDeposit);
                this.smsService.depositSms(clientInfo);
                break;

            case MonthlyPay_NEW:
                this.couponService.consumeCoupon(orderId, userId);
                this.couponCodeService.consumeCouponCode(orderId, userId);
                //新开通(更改押金状态)
                int adminUserId = Integer.parseInt(callbackResult.getAttach());
                QueryWrapper<AdminUser> q0 = new QueryWrapper<>();
                q0.select("department_id");
                q0.eq("id", adminUserId);
                Integer departmentId = this.adminUserService.getOne(q0).getDepartmentId();


                NewMonthlyBo newMonthlyInfo = this.monthlyfeeOrderService.getNewMonthlyInfo(userId, adminUserId);
                Integer adminNewMonUserId = newMonthlyInfo.getAdminUserId();
                if (!this.adminUserService.isSupplierAdminUser(adminNewMonUserId)) {
                    QueryWrapper<MonthlyfeeDeposit> q1 = new QueryWrapper<>();
                    q1.eq("user_id", userId);
                    q1.eq("status", DepositStatus.FREE.getStatus());
                    q1.last("limit 1");
                    MonthlyfeeDeposit mo = this.monthlyfeeDepositService.getOne(q1);
                    mo.setStatus(DepositStatus.OCCUPIED.getStatus());
                    this.monthlyfeeDepositService.updateById(mo);
                }


                Logistics logistics = new Logistics(orderId, newMonthlyInfo.getName(), newMonthlyInfo.getPhone(), newMonthlyInfo.getAddress());
                if (newMonthlyInfo.getProductId() != null) {
                    Integer productId = newMonthlyInfo.getProductId();
                    ProductDevice productDevice = this.productDeviceService.getById(productId);
                    if (productDevice != null) {
                        logistics.setRemarks(productDevice.getName() + "^" + productDevice.getType());
                    }
                }
                this.logisticsService.save(logistics);
                String countStr1 = this.stringRedisTemplate.opsForValue().get(orderId);
                int count1 = 1;
                if (countStr1 != null) {
                    count1 = Integer.parseInt(countStr1);
                }
                Date date1 = DateUtils.addDays(new Date(), count1 * 30);
                //生成包月订单
                MonthlyfeeOrder monthlyfeeOrder =
                        //默认赠送时间为0先
                        new MonthlyfeeOrder(orderId, userId, amountSum, 0, 0,
                                //失效时间从用户激活时开始算起 未分配机器id
                                date1, null,
                                //扫描了哪个业务员的码,就是哪个业务员的业绩
                                adminUserId, departmentId,
                                //物流在业务员进行派发机器时设置
                                MonthlyfeeOrderStatus.UNALLOCATED.getStatus(), logistics.getId());

                String depositId = this.stringRedisTemplate.opsForValue().get(ORDER_DEP + orderId);
                if (depositId != null) {
                    monthlyfeeOrder.setDepositId(depositId);
                    UpdateWrapper<MonthlyfeeDeposit> u5 = new UpdateWrapper<>();
                    u5.set("monthly_order_id", orderId);
                    u5.eq("order_id", depositId);
                    this.depositService.update(u5);
                }
                this.monthlyfeeOrderService.save(monthlyfeeOrder);
                this.smsService.newMonthly(new ClientInfo(newMonthlyInfo.getName(), newMonthlyInfo.getPhone(), newMonthlyInfo.getAddress(), newMonthlyInfo.getAdminUserId()));
                break;

            case MonthlyPay_CONTINUE:
                this.couponService.consumeCoupon(orderId, userId);
                this.couponCodeService.consumeCouponCode(orderId, userId);
                //续约(转移数据行)
                int deviceIdMon = Integer.parseInt(callbackResult.getAttach());
                //先查出剩余天数
                QueryWrapper<MonthlyfeeOrder> q2 = new QueryWrapper<>();
                q2.eq("user_id", userId);
                q2.eq("device_id", deviceIdMon);
                //需要是使用中状态
                q2.eq("status", MonthlyfeeOrderStatus.INUSE.getStatus());
                MonthlyfeeOrder monthlyfeeOrderOld = this.monthlyfeeOrderService.getOne(q2);
                //改为转移状态
                monthlyfeeOrderOld.setStatus(MonthlyfeeOrderStatus.TRANSFER.getStatus());
                //修改保存
                this.monthlyfeeOrderService.updateById(monthlyfeeOrderOld);
                //新数据行
                //放入新id
                monthlyfeeOrderOld.setOrderId(orderId);
                String countStr2 = this.stringRedisTemplate.opsForValue().get(orderId);
                int count2 = 1;
                if (countStr2 != null) {
                    count2 = Integer.parseInt(countStr2);
                }
                //多加三十天
                monthlyfeeOrderOld.setExpireTime(DateUtils.addDays(monthlyfeeOrderOld.getExpireTime(), 30 * count2));
                //写入新状态
                monthlyfeeOrderOld.setStatus(MonthlyfeeOrderStatus.INUSE.getStatus());
                //写入新金额
                monthlyfeeOrderOld.setOrderAmount(amountSum);
                //修正试用期和延长期
                monthlyfeeOrderOld.setTrialDay(0);
                monthlyfeeOrderOld.setExtendedDay(0);
                //保存
                this.monthlyfeeOrderService.save(monthlyfeeOrderOld);
                break;

            case REFUND_PAY:
                /**
                 * 退款需要改什么?
                 * 1.退款表 状态
                 * 2.机器用户映射表 删除
                 * 3.月费押金表 删除
                 * 4.月费机器 状态
                 * 5.月费订单 状态
                 */
                orderId = orderId.substring(2);
                MonthlyRefundDeposit refundDeposit = this.refundDepositService.getById(Integer.parseInt(orderId));
                refundDeposit.setStatus(ReturnDepositStatus.OK.getStatus());
                //退款表
                this.refundDepositService.updateById(refundDeposit);
                //订单表
                QueryWrapper<MonthlyfeeOrder> q3 = new QueryWrapper<>();
                q3.select("order_id", "device_id");
                q3.eq("order_id", refundDeposit.getOrderId());
                MonthlyfeeOrder mOrder = this.monthlyfeeOrderService.getOne(q3);
                mOrder.setStatus(MonthlyfeeOrderStatus.COMPLETED.getStatus());
                this.monthlyfeeOrderService.updateById(mOrder);
                //押金表
                this.depositService.removeById(refundDeposit.getDepositId());
                //机器用户映射表
                QueryWrapper<MonthlyUserDevice> q4 = new QueryWrapper<>();
                q4.eq("device_id", mOrder.getDeviceId());
                this.userDeviceService.remove(q4);
                //机器表
                UpdateWrapper<MonthlyfeeDevice> u1 = new UpdateWrapper<>();
                u1.set("status", MonthlyDeviceStatus.FREE.getStatus());
                u1.eq("id", mOrder.getDeviceId());
                this.monthlyfeeDeviceService.update(u1);
                break;
            case BUY_PAY:
                //购买业务,保存进入订单表即可
                int adminUserIdByBuy = Integer.parseInt(callbackResult.getAttach());
                LogisticsBuy logisticsBuy = this.buyOrderService.getLogisticsBuy(adminUserIdByBuy, userId);
                logisticsBuy.setBuyOrderId(orderId);
                this.logisticsBuyService.save(logisticsBuy);
                BuyOrder buyOrder = new BuyOrder(orderId, callbackResult.getPayerTotal(), callbackResult.getUserId(), adminUserIdByBuy, this.adminUserService.getDepId(adminUserIdByBuy), logisticsBuy.getId(), BuyOrderStatus.unallocated.getStatus());
                this.buyOrderService.save(buyOrder);
                this.smsService.buySms(new ClientInfo(logisticsBuy.getName(), logisticsBuy.getPhone(), logisticsBuy.getAddress(), adminUserIdByBuy));
                break;
            case BUY_REFUND:
                /**
                 * 购买业务退款了
                 * 1.机器是否分配了,分配了就删除 臭氧+氧气
                 * 2.订单状态
                 */
                QueryWrapper<BuyOrder> q5 = new QueryWrapper<>();
                q5.select("order_id", "device_id");
                q5.eq("order_id", orderId);
                BuyOrder buyOrderREFUND = this.buyOrderService.getOne(q5);
                buyOrderREFUND.setStatus(BuyOrderStatus.refunded.getStatus());
                this.buyOrderService.updateById(buyOrderREFUND);
                Integer deviceId = buyOrderREFUND.getDeviceId();
                if (deviceId != null) {
                    //删除对应的机器
                    QueryWrapper<BuyOzoneDevice> q6 = new QueryWrapper<>();
                    q6.select("oxygen_id");
                    q6.eq("id", deviceId);
                    Integer oxygenId = this.buyOzoneDeviceService.getOne(q6).getOxygenId();
                    this.buyOzoneDeviceService.removeById(deviceId);
                    this.buyOxygenDeviceService.removeById(oxygenId);
                }
                break;
            default:
                break;
        }
        log.info("支付类型:{}, 回调信息:{}", payType.getDescription(), JSON.toJSONString(callbackResult));
    }

    /**
     * 单次支付优惠券专用
     * 获取orderId
     */
    public static String getOrderId() {
        String orderId = orderThreadLocal.get();
        orderThreadLocal.remove();
        return orderId;
    }

}
